#include "my_timer.h"
#include "systick.h"

static my_timer_t tm_header = 0;//定时器链表头


/**
 * @brief 注册定时器,时基定时器为systick中定义的时基
 *
 * @param tm 定时器指针
 */
void timer_register(my_timer_t tm)
{
    tm->next = 0;
    tm->time = 0;
    tm->time_tick = 0;
    tm->timer_callback = 0;
    tm->is_use = 0;

    if (tm_header == 0)
    {
        tm_header = tm;
    }
    else
    {
        my_timer_t looper = tm_header;
        while (looper->next != 0)
        {
            looper = looper->next;
        }
        looper->next = tm;
    }
}

/**
 * @brief 定时器是否被置位
 *
 * @param tm
 * @return char 1为定时器时间到了被置位还未处理,需要timer_set_clear清空
 */
char timer_is_set(my_timer_t tm)
{
    return tm->set;
}

/**
 * @brief 清空事件置位
 *
 * @param tm
 */
void timer_set_clear(my_timer_t tm)
{
    tm->set = 0;
}

/**
 * @brief 定时器触发时间重置,将触发时间改为time个tick并从start_time重新开始计时
 *
 * @param tm
 * @param time 希望多少time之后触发
 */
void timer_tick_reset(my_timer_t tm, unsigned long time, unsigned long start_time)
{
    tm->time = time;
    tm->time_tick = get_systick() + time + start_time;
}

/**
 * @brief 立即触发一次定时器
 * 
 * @param tm 
 */
void timer_trigger(my_timer_t tm)
{
    tm->time_tick = get_systick();
}
/**
 * @brief
 *
 * @param tm
 * @param time time个tick触发一次
 * @param start_time start_time 从start_time开始计时
 * @param num 触发次数,取值0-63,0为无限次循环
 * @param timer_callback 定时器超时回调
 */
void timer_set(my_timer_t tm, unsigned long time, unsigned long start_time, unsigned char num, void (*timer_callback)(void *), void *userdata)
{
    tm->time = time;
    tm->time_tick = time + get_systick() + start_time;
    tm->num = num;
    tm->timer_callback = timer_callback;
    tm->userdata = userdata;
}

/**
 * @brief 定时器注册和设置2和一函数
 *
 * @param tm
 * @param time 定时器时间
 * @param num 运行次数
 * @param timer_callback 超时回调
 * @param use 是否开始定时器
 */
void timer_register_set(my_timer_t tm, unsigned long time, unsigned long start_time, unsigned char num, void (*timer_callback)(void *), void *userdata, unsigned char use)
{
    timer_register(tm);
    timer_set(tm, time, start_time, num, timer_callback, userdata);
    tm->is_use = use;
    tm->userdata = userdata;
}

/**
 * @brief 开始定时器
 *
 * @param tm
 */
void timer_start(my_timer_t tm)
{
    tm->is_use = 1;
}
/**
 * @brief 定时器停止
 *
 * @param tm
 */
void timer_stop(my_timer_t tm)
{
    tm->is_use = 0;
}

/**
 * @brief 定时器工作线程,不要在该线程内做阻塞操作
 *
 */
void timer_thread()
{
    my_timer_t looper = tm_header;
    while (looper != 0)
    {
        if (looper->set == 1 && looper->timer_callback)
        {
            looper->set = 0;
            looper->timer_callback(looper->userdata);
        }
        looper = looper->next;
    }
}

/**
 * @brief 定时器中断线程,计算定时器事件
 *
 * @param systick
 */
void timer_irq(unsigned long systick)
{
    my_timer_t looper = tm_header;
    while (looper != 0)
    {
        if (looper->is_use)
        {
            if ((looper->time_tick - systick) >= (systick - looper->time_tick))
            {
                looper->time_tick += looper->time;
                looper->set = 1;
                if (looper->num > 0)
                {
                    looper->num--;
                    if (looper->num == 0)
                    {
                        looper->is_use = 0;
                    }
                }
            }
        }
        else
        {
            looper->time_tick++;
        }
        looper = looper->next;
    }
}

